﻿#include<iostream>
#include<memory>
#include<functional>
#include<atomic>
using namespace std;

//double Divide(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		throw "Divide by zero condition!";
//	} 
//	else
//	{
//	return (double)a / (double)b;
//	}
//} 
//void Func()
//{
//	int* array1 = new int[10];
//	int* array2 = new int[10]; // 抛异常呢
//	try
//	{
//		int len, time;
//		cin >> len >> time;
//		cout << Divide(len, time) << endl;
//	} 
//	catch(...)
//	{
//		cout << "delete []" << array1 << endl;
//		cout << "delete []" << array2 << endl;
//		delete[] array1;
//		delete[] array2;
//		throw; // 异常重新抛出，捕获到什么抛出什么
//	}
//	cout << "delete []" << array1 << endl;
//	delete[] array1;
//	cout << "delete []" << array2 << endl;
//	delete[] array2;
//} 
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch(const char* errmsg)
//	{
//		cout << errmsg << endl;
//	} 
//	catch(const exception & e)
//	{
//		cout << e.what() << endl;
//	} 
//	catch(...)
//	{
//		cout << "未知异常" << endl;
//	} 
//	return 0;
//}

//template<class T>
//class SmartPtr
//{
//	public :
//	// RAII
//	SmartPtr(T* ptr)
//		: _ptr(ptr)
//	{}
//	~SmartPtr()
//	{
//		cout << "delete[] " << _ptr << endl;
//		delete[] _ptr;
//	} 
//	// 重载运算符，模拟指针的行为，方便访问资源
//	T & operator*()
//	{
//		return *_ptr;
//	} 
//	
//	T* operator->()
//	{
//		return _ptr;
//	} T
//		& operator[](size_t i)
//	{
//		return _ptr[i];
//	}
//private:
//	T* _ptr;
//};
//double Divide(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		throw "Divide by zero condition!";
//	} 
//	else
//	{
//		return (double)a / (double)b;
//	}
//} 
//
//void Func()
//{
//	// 这里使用RAII的智能指针类管理new出来的数组以后，程序简单多了
//	//将资源的生命周期绑定到对象的生命周期
//	//对象构造时获取资源，对象析构时自动释放资源
//	SmartPtr<int> sp1 = new int[10];
//	SmartPtr<int> sp2 = new int[10];
//	for (size_t i = 0; i < 10; i++)
//	{
//		sp1[i] = sp2[i] = i;
//	} 
//	int len, time;
//	cin >> len >> time;
//	cout << Divide(len, time) << endl;
//} 
//int main()
//{
//	try
//	{
//		Func();
//	} 
//	catch(const char* errmsg)
//	{
//		cout << errmsg << endl;
//	} 
//	catch(const exception & e)
//	{
//		cout << e.what() << endl;
//	} 
//	catch(...)
//	{
//		cout << "未知异常" << endl;
//	} 
//	return 0;
//}

struct Date
{
	int _year;
	int _month;
	int _day;
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}
	~Date()
	{
		cout << "~Date()" << endl;
	}
};

//int main()
//{
//	auto_ptr<Date> ap1(new Date);
//	// 拷贝时，管理权限转移，被拷贝对象ap1悬空
//	auto_ptr<Date> ap2(ap1);
//	// 空指针访问，ap1对象已经悬空
//	//ap1->_year++;
//	return 0;
//}

//int main()
//{
//	unique_ptr<Date> up1(new Date);
//	// 不支持拷贝
//	//unique_ptr<Date> up2(up1);
//	
//	// 支持移动，但是移动后up1也悬空，所以使用移动要谨慎
//	//因为移动构造有被掠夺资源的风险，这里默认是你知道
//	//你自己move的，就说明你知道有风险，所有才说他们本质是设计思路的不同
//	unique_ptr<Date> up3(move(up1));
//	return 0;
//}

//int main()
//{
//	shared_ptr<Date> sp1(new Date);
//	// 支持拷贝
//	shared_ptr<Date> sp2(sp1);
//	shared_ptr<Date> sp3(sp2);
//
//	cout << sp1.use_count() << endl;
//	sp1->_year++;
//	cout << sp1->_year << endl;
//	cout << sp2->_year << endl;
//	cout << sp3->_year << endl;
//	// 支持移动，但是移动后sp1也悬空，所以使用移动要谨慎
//	shared_ptr<Date> sp4(new Date);
//	sp2 = sp4;
//	cout << sp1.use_count() << endl;
//	cout << sp4.use_count() << endl;
//	return 0;
//}

namespace xin
{
	template<class T>
	class auto_ptr
	{
	public:
		auto_ptr(T* ptr)
			: _ptr(ptr)
		{}

		auto_ptr(auto_ptr<T>& sp)
			:_ptr(sp._ptr)
		{
			sp._ptr = nullptr;//管理权转移
		}

		auto_ptr<T>& operator=(auto_ptr<T>& ap)
		{
			if (*this != ap)
			{
				if (_ptr)
				{
					//释放当前资源
					delete _ptr;
				}

				//将ap的资源转移给当前对象
				_ptr = ap._ptr;
				ap._ptr = nullptr;
			}
			return *this;
		}

		~auto_ptr()
		{
			if (_ptr)
			{
				cout << "delete:" << _ptr << endl;
				delete _ptr;
			}
		}

		// 像指针⼀样使⽤
		T & operator*()
		{
			return *_ptr;
		} 
		
		T* operator->()
		{
			return _ptr;
		}

	private:
		T* _ptr;
	};

	template<class T>
	class unique_ptr
	{
	public:
		explicit unique_ptr(T* ptr)
			:_ptr(ptr)
		{}

		~unique_ptr()
		{
			if (_ptr)
			{
				cout << "delete:" << _ptr << endl;
				delete _ptr;
			}
		}
		
		//不支持拷贝
		unique_ptr(const unique_ptr<T>& up) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>& up) = delete;

		//支持移动
		unique_ptr(unique_ptr<T>&& up)
			:_ptr(up._ptr)
		{
			up._ptr = nullptr;
		}

		unique_ptr<T>& operator=( unique_ptr<T>&& up)
		{
			delete _ptr;
			_ptr = up._ptr;
			up._ptr = nullptr;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T& operator->()
		{
			return _ptr;
		}

	private:
		T* _ptr;

	};

	template<class T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr = nullptr )//标准库里支持无参构造
			:_ptr(ptr)
			,_pcount(new atomic<int>(1))//_pcount(new int(1))
		{}

		template<class D>
		shared_ptr(T* ptr ,D del)
			:_ptr(ptr)
			,_pcount(new int(1))
			,_del(del)
		{}

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _del(sp._del)
		{
			++(*_pcount);
		}

		void release()
		{
			if (--(*_pcount)==0)
			{
				//最后一个管理的对象，释放资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			if (_ptr != sp._ptr)
			{
				release();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}

			return *this;
		}

		~shared_ptr()
		{
			release();
		}

		T* get() const
		{
			return _ptr;
		}

		int use_count() const
		{
			return *_pcount;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		atomic<int>* _pcount; //原子操作
		//int* _pcount;
		
		function<void(T*)> _del = [](T* ptr) {delete ptr; };//包装器来包装删除器，默认使用lambda
	};

	template<class T>
	class weak_ptr
	{
	public:
		weak_ptr()
		{}

		weak_ptr(const shared_ptr<T>& sp)
			:_ptr(sp.get())
		{}

		weak_ptr<T>& operator=(const shared_ptr<T>& sp)
		{
			_ptr = sp.get();

			return *this;
		}

	private:
		T* _ptr = nullptr;
	};
}

int main()
{
	shared_ptr<string> sp1(new string("111111"));
	shared_ptr<string> sp2(sp1);
	weak_ptr<string> wp = sp1;
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	// sp1和sp2都指向了其他资源，则weak_ptr就过期了
	sp1 = make_shared<string>("222222");
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	sp2 = make_shared<string>("333333");
	cout << wp.expired() << endl;
	cout << wp.use_count() << endl;
	
	return 0;
}

//struct ListNode
//{
//	int _data;
//	std::shared_ptr<ListNode> _next;
//	std::shared_ptr<ListNode> _prev;
//	
//	~ListNode()
//	{
//		cout << "~ListNode()" << endl;
//	}
//};
//int main()
//{
//	// 循环引⽤ -- 内存泄露
//	shared_ptr<ListNode> n1(new ListNode);
//	shared_ptr<ListNode> n2(new ListNode);
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//	n1->_next = n2;
//	n2->_prev = n1;
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//	
//	return 0;
//}

//struct ListNode
//{
//	int _data;
//	
//	// 这⾥改成weak_ptr，当n1->_next = n2;绑定shared_ptr时
//	// 不增加n2的引用计数，不参与资源释放的管理，就不会形成循环引用了
//	std::weak_ptr<ListNode> _next;
//	std::weak_ptr<ListNode> _prev;
//
//	~ListNode()
//	{
//		cout << "~ListNode()" << endl;
//	}
//};
//int main()
//{
//	// 循环引⽤ -- 内存泄露
//	std::shared_ptr<ListNode> n1(new ListNode);
//	std::shared_ptr<ListNode> n2(new ListNode);
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//	n1->_next = n2;
//	n2->_prev = n1;
//	cout << n1.use_count() << endl;
//	cout << n2.use_count() << endl;
//	
//	return 0;
//}

//int main()
//{
//	 //这样实现程序会崩溃
//	 /*unique_ptr<Date> up1(new Date[10]);
//	 shared_ptr<Date> sp1(new Date[10]);*/
//
//	// 解决⽅案1
//	// 因为new[]经常使⽤，所以unique_ptr和shared_ptr
//	// 实现了⼀个特化版本，这个特化版本析构时用的delete[]
//	unique_ptr<Date[]> up1(new Date[5]);
//	shared_ptr<Date[]> sp1(new Date[5]);
//
//	return 0;
//}
//#include<file>

//template<class T>
//void DeleteArrayFunc(T* ptr)
//{
//	delete[] ptr;
//}
//
//template<class T>
//class DeleteArray
//{
//	public :
//	void operator()(T* ptr)
//	{
//		delete[] ptr;
//	}
//};
//class Fclose
//{
//	public :
//	void operator()(FILE* ptr)
//	{
//		cout << "fclose:" << ptr << endl;
//		fclose(ptr);
//	}
//};
//
//int main()
//{
//	// 解决方案2
//	// 仿函数对象做删除器
//	// unique_ptr和shared_ptr支持删除器的方式有所不同
//	// unique_ptr是在类模板参数支持的，shared_ptr是构造函数参数支持的
//	// unique_ptr<Date, DeleteArray<Date>> up2(new Date[5], DeleteArray<Date>());
//	// 这里没有使用相同的方式还是挺坑的
//	// 使用仿函数unique_ptr可以不在构造函数传递，因为仿函数类型构造的对象直接就可以调用
//	// 但是下面的函数指针和lambda的类型不可以
//	unique_ptr<Date, DeleteArray<Date>> up2(new Date[5]);//可以不在构造函数传递
//	shared_ptr<Date> sp2(new Date[5], DeleteArray<Date>());//在构造函数传递
//	
//	// 函数指针做删除器
//	unique_ptr<Date, void(*)(Date*)> up3(new Date[5], DeleteArrayFunc<Date>);
//	shared_ptr<Date> sp3(new Date[5], DeleteArrayFunc<Date>);
//
//	// lambda表达式做删除器
//	auto delArrOBJ = [](Date* ptr) {delete[] ptr; };//我们无法知道lambda的类型
//	unique_ptr<Date, decltype(delArrOBJ)> up4(new Date[5], delArrOBJ);//
//	//但是这里要显示传类型，就用了decltype,其作用是查询表达式的类型
//	shared_ptr<Date> sp4(new Date[5], delArrOBJ);
//
//	// 实现其他资源管理的删除器
//	shared_ptr<FILE> sp5(fopen("Test.cpp", "r"), Fclose());
//	shared_ptr<FILE> sp6(fopen("Test.cpp", "r"), [](FILE* ptr) {
//		cout << "fclose:" << ptr << endl;
//		fclose(ptr);
//		});
//	return 0;
//}

//int main()
//{
//	shared_ptr<Date> sp1(new Date(2024, 9, 11));
//	shared_ptr<Date> sp2 = make_shared<Date>(2024, 9, 11);
//	auto sp3 = make_shared<Date>(2024, 9, 11);
//	shared_ptr<Date> sp4;//支持无参构造
//	// if (sp1.operator bool())
//	if (sp1)
//		cout << "sp1 is not nullptr" << endl;
//	if (!sp4)
//		cout << "sp4 is nullptr" << endl;
//	// 报错 因为它们的构造函数都不支持隐士类型转化
//	//shared_ptr<Date> sp5 = new Date(2024, 9, 11);
//	//unique_ptr<Date> sp6 = new Date(2024, 9, 11);
//	return 0;
//}

//int main()
//{
//	shared_ptr<Date> sp1(new Date);
//	// 支持拷贝
//	shared_ptr<Date> sp2(sp1);
//	shared_ptr<Date> sp3(sp2);
//
//	cout << sp1.use_count() << endl;
//	sp1->_year++;
//	cout << sp1->_year << endl;
//	cout << sp2->_year << endl;
//	cout << sp3->_year << endl;
//	// 支持移动，但是移动后sp1也悬空，所以使用移动要谨慎
//	/*shared_ptr<Date> sp4(new Date);
//	sp2 = sp4;*/
//	sp1 = sp2;
//	cout << sp1.use_count() << endl;
//	cout << sp2.use_count() << endl;
//	return 0;
//	return 0;
//}